type point = float * float

type shape =
  | Point  of point
  | Circle of point * float (* center and radius *)
  | Rect   of point * point (* lower-left and
                               upper-right corners *)

let pi = 3.1415926

let area = function
  | Point x -> 0.0
  | Circle (_, r) -> pi *. r *. r
  | Rect ((x0, y0), (x1, y1)) -> Float.abs ((x0 -. x1) *. (y0 -. y1))

type 'a mylist = Nil | Cons of 'a * 'a mylist

let rec sum = function
  | Nil -> 0
  | Cons (v, next) -> v + sum next

let rec length = function
  | Nil -> 0
  | Cons (_,t) -> 1 + length t

let empty = function
  | Nil -> true
  | Cons _ -> false

type node = {value:int; next:intlist}
and intlist = Nil | Node of node

(* note: no type definition *)
(* 匿名 adt  *)
let foo = function
  | 0 -> `Infinity
  | 1 -> `Finite 1
  | n -> `Finite (-n)

(* 处理匿名 adt  *)
(* 注意类型，会进行分支检查  *)
let bar = function
  | `Infinity -> "Infinity"
  | `Finite n -> "Finite"
  | `NegInfinity -> "negative infinity"

type nat = Zero | Succ of nat

let rec int_to_nat = function
  | 0 -> Zero
  | x when x > 0 -> Succ (int_to_nat (x - 1))
  | _ -> raise (Invalid_argument "need int >= 0")
